﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using BrnMall.Business;
using BrnMall.CacheManager;
using BrnMall.Core;
using BrnMall.Manager;
using BrnMall.Manager.Domain.Product;
using BrnMall.Manager.Domain.Promotion;
using BrnMall.Manager.Domain.Store;
using BrnMall.Manager.Domain.WeApp;
using BrnMall.Manager.Manager.Product;
using BrnMall.Manager.Manager.Promotion;
using BrnMall.Manager.Manager.Store;
using BrnMall.Manager.Manager.WeApp;
using BrnMall.Sdk.QQMap;
using BrnMall.Services;
using Newtonsoft.Json;
using PetaPoco;
using QIDong.WeApp.Models;
using QIDong.WeApp.Util;
using WeiTap.Restful;
using BrnMall.WeiXin.Sdk;
using BrnMall.Sdk.WeiXin;
using BrnMall.Core.Helper;
using BrnMall.Manager.Manager.Log;

namespace QIDong.WeApp.Controllers
{
    /// <summary>
    /// 店铺管理
    /// </summary>
    public class StoreController : WebApi
    {
        /// <summary>
        /// 获取店铺信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public StoreInfo GetInfo(int id)
        {
            try
            {
                var info = Stores.GetStoreById(id);
                return info;
            }
            catch (Exception e)
            {
                throw new ApiException(ExceptionCode.DataError, e.Message);
            }
        }

        /// <summary>
        /// 获取店铺信息
        /// </summary>
        /// <param name="openId"></param>
        /// <returns></returns>
        public StoreInfo GetInfoByOpenId(string openId)
        {
            try
            {
                var uid = OAuths.GetUidByOpenIdAndServer(openId, "dyb");
                if (uid < 1)
                    throw new ApiException(ExceptionCode.DataNotFound, openId);
                var partUserInfo = Users.GetPartUserById(uid);
                if (partUserInfo.StoreId == 0)
                    throw new ApiException(ExceptionCode.DataInvalid, "店铺ID");
                var info = Stores.GetStoreById(partUserInfo.StoreId);
                return info;
            }
            catch (Exception e)
            {
                throw new ApiException(ExceptionCode.DataError, e.Message);
            }
        }

        /// <summary>
        /// 更新店铺信息
        /// </summary>
        /// <param name="openId"></param>
        /// <param name="supportcompany">技术支持公司</param>
        /// <param name="supportphone">支持电话</param>
        /// <returns></returns>
        public bool UpdateInfoByOpenId(string openId, string supportcompany, string supportphone)
        {
            var uid = OAuths.GetUidByOpenIdAndServer(openId, "dyb");
            if (uid < 1)
                throw new ApiException(ExceptionCode.DataNotFound, openId);
            var partUserInfo = Users.GetPartUserById(uid);
            if (partUserInfo.StoreId == 0)
                throw new ApiException(ExceptionCode.DataInvalid, "店铺ID");
            if (string.IsNullOrEmpty(supportcompany))
                throw new ApiException(ExceptionCode.DataNotFound, supportcompany);
            if (string.IsNullOrEmpty(supportphone))
                throw new ApiException(ExceptionCode.DataNotFound, supportphone);
            var store = Stores.GetStoreById(partUserInfo.StoreId);
            store.SupportPhone = supportphone;
            store.SupportCompany = supportcompany;
            AdminStores.UpdateStore(store);
            LogManager.Add(new BrnMall.Manager.Domain.Log.Logs()
            {
                DataType = 1,
                Details = $"修改小程序底部信息,supportcompany={supportcompany},supportphone={supportphone},openIds:{openId}",
                CreateTime = DateTime.Now
            });
            return true;
        }

        /// <summary>
        /// 更新店铺信息
        /// </summary>
        /// <param name="openIds">用逗号分隔</param>
        /// <param name="supportcompany">技术支持公司</param>
        /// <param name="supportphone">支持电话</param>
        /// <returns></returns>
        public bool BatchUpdateInfoByOpenId(string openIds, string supportcompany = "", string supportphone = "")
        {
            if (string.IsNullOrEmpty(openIds))
                throw new ArgumentNullException(nameof(openIds));

            Task.Factory.StartNew(() =>
            {
                var ids = openIds.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                var okDetail = new System.Text.StringBuilder();
                foreach (var openId in ids)
                {
                    var uid = OAuths.GetUidByOpenIdAndServer(openId, "dyb");
                    if (uid < 1)
                        continue;
                    var partUserInfo = Users.GetPartUserById(uid);
                    if (partUserInfo.StoreId == 0)
                        continue;
                    var store = Stores.GetStoreById(partUserInfo.StoreId);
                    store.SupportPhone = supportphone;
                    store.SupportCompany = supportcompany;
                    AdminStores.UpdateStore(store);
                    okDetail.AppendFormat("{0},", openId);
                }

                LogManager.Add(new BrnMall.Manager.Domain.Log.Logs()
                {
                    DataType = 1,
                    Details = $"修改小程序底部信息,supportcompany={supportcompany},supportphone={supportphone},openIds:{openIds},成功的openIds:{okDetail.ToString()}",
                    CreateTime = DateTime.Now
                });
            });

            return true;
        }

        /// <summary>
        /// 获取下级店铺（用于平台入驻功能）
        /// </summary>
        /// <param name="pid"></param>
        /// <param name="name">店铺名</param>
        /// <param name="pageSize"></param>
        /// <param name="pageNumber"></param>
        /// <returns></returns>
        public List<StoreModel> GetChildStore(int pid, string name = "", int pageSize = 15, int pageNumber = 1, double lat = 0, double lng = 0)
        {
            try
            {
                var condition = AdminStores.AdminGetStoreListCondition(name, 0, 0, 0, pid);
                var result = AdminStores.AdminGetStoreList(pageSize, pageNumber, condition);
                var list = new List<StoreModel>();
                foreach (DataRow row in result.Rows)
                {
                    var store = new StoreModel
                    {
                        StoreId = TypeHelper.ObjectToInt(row["storeid"]),
                        State = TypeHelper.ObjectToInt(row["state"]),
                        Address = row["address"].ToString(),
                        Announcement = row["announcement"].ToString(),
                        Banner = row["banner"].ToString(),
                        CreateTime = TypeHelper.ObjectToDateTime(row["createtime"]),
                        Description = row["description"].ToString(),
                        DePoint = TypeHelper.ObjectToDecimal(row["depoint"]),
                        SePoint = TypeHelper.ObjectToDecimal(row["sepoint"]),
                        ShPoint = TypeHelper.ObjectToDecimal(row["shpoint"]),
                        Honesties = TypeHelper.ObjectToInt(row["honesties"]),
                        StateEndTime = TypeHelper.ObjectToDateTime(row["stateendtime"])
                    };
                    store.Banner = row["banner"].ToString();
                    store.Fax = row["fax"].ToString();
                    store.Location = row["location"].ToString();
                    store.Logo = row["logo"].ToString();
                    store.Mobile = row["mobile"].ToString();
                    store.Phone = row["phone"].ToString();
                    store.QQ = row["qq"].ToString();
                    store.RegionId = TypeHelper.ObjectToInt(row["regionid"]);
                    store.StoreIid = TypeHelper.ObjectToInt(row["storeiid"]);
                    store.StoreRid = TypeHelper.ObjectToInt(row["storerid"]);
                    store.Name = row["name"].ToString();
                    store.Theme = row["theme"].ToString();
                    store.WW = row["ww"].ToString();
                    if (store.RegionId > 0)
                    {
                        var region = Regions.GetRegionById(store.RegionId);
                        store.RegionName = region.Name;
                    }

                    var lat2 = 22.543721D; var lng2 = 114.101514D;
                    if (store.Location.Contains(','))
                    {
                        double.TryParse(store.Location.Split(',')[0], out lat2);
                        double.TryParse(store.Location.Split(',')[1], out lng2);
                    }
                    var distance = QQMapApi.GetDistance(lat, lng, lat2, lng2);
                    store.Distance = distance;
                    if (distance < 1000)
                        store.DistanceShow = "<1公里";
                    else if (distance < 2000)
                        store.DistanceShow = "<2公里";
                    else if (distance < 5000)
                        store.DistanceShow = "<5公里";
                    else if (distance < 10000)
                        store.DistanceShow = "<10公里";
                    else
                        store.DistanceShow = ">10公里";
                    list.Add(store);
                }
                return list.OrderBy(t => t.Distance).ToList();
            }
            catch (Exception e)
            {
                Trace.TraceInformation(e.Message);
                throw;
            }
        }

        /// <summary>
        /// 获取店铺小程序设置
        /// </summary>
        /// <param name="id"></param>
        /// <param name="weAppId">小程序配置ID</param>
        /// <returns></returns>
        public StoreWxApp GetStoreWxApp(int id, int weAppId = 0)
        {
            try
            {
                var app = StoreWxAppManager.GetStoreDefaultWxAppById(id, weAppId);
                return app;
            }
            catch (Exception e)
            {
                throw new ApiException(ExceptionCode.DataError, e.Message);
            }
        }

        /// <summary>
        /// 更新小程序设置
        /// </summary>
        /// <param name="openId">第三方登录用户名</param>
        /// <param name="appId"></param>
        /// <param name="secret"></param>
        /// <param name="weAppId">小程序配置ID</param>
        /// <returns></returns>
        public bool UpdateStoreWxApp(string openId, string appId, string secret, int weAppId = 0)
        {
            try
            {
                var uid = OAuths.GetUidByOpenIdAndServer(openId, "dyb");
                if (uid < 1)
                    throw new ApiException(ExceptionCode.DataNotFound, openId);
                if (string.IsNullOrEmpty(appId))
                    throw new ArgumentNullException(nameof(openId));
                if (string.IsNullOrEmpty(secret))
                    throw new ArgumentNullException(nameof(secret));
                var partUserInfo = Users.GetPartUserById(uid);
                if (partUserInfo.StoreId == 0)
                    throw new ApiException(ExceptionCode.DataInvalid, "店铺ID");

                var old = StoreWxAppManager.GetStoreDefaultWxAppById(partUserInfo.StoreId, weAppId);
                if (old == null)
                {
                    var list = StoreWxAppManager.GetStoreWxAppList(partUserInfo.StoreId);
                    old = list.Count > 0 ? list.First() : new StoreWxApp();
                    old.IsDefault = true;
                }
                old.StoreId = partUserInfo.StoreId;
                old.WeAppId = appId;
                old.WeAppSecret = secret;
                StoreWxAppManager.UpdateOrAddStoreWxApp(old);
                return true;
            }
            catch (Exception e)
            {
                Trace.TraceError(e.Message);
                throw;
            }
        }

        /// <summary>
        /// 更新小程序设置
        /// </summary>
        /// <param name="openId">第三方登录用户名</param>
        /// <param name="mchId"></param>
        /// <param name="key"></param>
        /// <param name="weAppId">小程序配置ID</param>
        /// <returns></returns>
        public bool UpdateStoreWxPay(string openId, string mchId, string key, int weAppId = 0)
        {
            try
            {
                var uid = OAuths.GetUidByOpenIdAndServer(openId, "dyb");
                if (uid < 1)
                    throw new ApiException(ExceptionCode.DataNotFound, openId);
                var partUserInfo = Users.GetPartUserById(uid);
                if (partUserInfo.StoreId == 0)
                    throw new ApiException(ExceptionCode.DataInvalid, "店铺ID");
                if (string.IsNullOrEmpty(mchId))
                    throw new ArgumentNullException(nameof(mchId));
                if (string.IsNullOrEmpty(key))
                    throw new ArgumentNullException(nameof(key));

                var old = StoreWxAppManager.GetStoreDefaultWxAppById(partUserInfo.StoreId, weAppId);
                if (old == null)
                {
                    var list = StoreWxAppManager.GetStoreWxAppList(partUserInfo.StoreId);
                    old = list.Count > 0 ? list.First() : new StoreWxApp();
                    old.IsDefault = true;
                }
                old.StoreId = partUserInfo.StoreId;
                old.MchId = mchId;
                old.MchKey = key;
                StoreWxAppManager.UpdateOrAddStoreWxApp(old);
                return true;
            }
            catch (Exception e)
            {
                Trace.TraceError(e.Message);
                throw;
            }
        }

        #region 店铺分类

        /// <summary>
        /// 获取店铺分类列表
        /// </summary>
        /// <param name="store_id">店铺ID</param>
        /// <returns></returns>
        public List<StoreClassInfo> GetClassList(int store_id)
        {
            if (store_id < 1)
                throw new ApiException("请输入店铺ID");
            try
            {
                return Stores.GetStoreClassList(store_id);
            }
            catch (Exception e)
            {
                Trace.TraceError(e.Message);
                throw;
            }
        }

        /// <summary>
        /// 获取单个店铺分类详情
        /// </summary>
        /// <param name="store_id"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public StoreClassInfo GetClass(int store_id, int id)
        {
            if (store_id < 1)
                throw new ApiException("请输入店铺分类ID");
            try
            {
                return Stores.GetStoreClassByStoreIdAndStoreCid(store_id, id);
            }
            catch { throw; }
        }

        #endregion 店铺分类

        #region 店铺商品分类

        /// <summary>
        /// 商品分类列表
        /// </summary>
        /// <param name="storeId">店铺ID</param>
        /// <returns></returns>
        public List<StoreClassInfo> GetStoreClassList(int storeId)
        {
            try
            {
                return Stores.GetStoreClassList(storeId);
            }
            catch (Exception e)
            {
                Trace.TraceError(e.Message);
                throw;
            }
        }

        #endregion 店铺商品分类

        #region 店铺商品

        /// <summary>
        /// 首页 分类商品列表
        /// </summary>
        /// <param name="storeId">店铺ID</param>
        /// <param name="cateId">商品分类ID</param>
        /// <param name="trait"> 商品特征(0代表精品,1代表热销,2代表新品)，不填默认是精品</param>
        /// <param name="count">返回的商品总条数,不填默认是3条</param>
        /// <returns></returns>
        public List<ProductListOutDto> GetStoreTraitProductList(int storeId, int trait, int cateId = 0, int count = 8)
        {
            var productList = Products.GetStoreTraitProductList(count, storeId, cateId, trait, 2);
            return productList.Select(MapperFromProduct).ToList();
        }

        /// <summary>
        /// 首页 分类商品列表
        /// </summary>
        /// <param name="storeId">店铺ID</param>
        /// <param name="cateId">商品分类ID</param>
        /// <param name="trait"> 商品特征(0代表精品,1代表热销,2代表新品)，不填默认是精品</param>
        /// <param name="count">返回的商品总条数,不填默认是3条</param>
        /// <returns></returns>
        public List<ProductListOutDto> GetSessionStoreTraitProductList(int storeId, int trait, int cateId = 0, int count = 8)
        {
            var productList = Products.GetStoreTraitProductList(count, storeId, cateId, trait, saleMode: 1);
            return productList.Select(MapperFromProduct).ToList();
        }

        /// <summary>
        /// 线下商品搜索
        /// </summary>
        /// <returns></returns>
        public StoreSearchModel SessionSearch(int storeId, int cateId, int page, string word = "", int pageSize = 20, int priceStart = 0, int priceEnd = 0, int sortColumn = 0, int sortDirection = 0, string priceTime = "")
        {
            try
            {
                page = page < 1 ? 1 : page;

                //商品总数量
                int totalCount = 0;
                //商品列表
                List<PartProductInfo> productList = null;
                if (!string.IsNullOrEmpty(word))
                    Searches.SearchStoreProducts(pageSize, page, word, storeId, cateId, priceStart, priceEnd, sortColumn, sortDirection, ref totalCount, ref productList, saleMode: 1);
                else
                {
                    totalCount = Products.GetStoreClassProductCount(cateId, 0, 0, storeId, saleMode: 1);
                    productList =
                        Products.GetStoreClassProductList(pageSize, page, cateId, storeId, priceStart, priceEnd, sortColumn, sortDirection, saleMode: 1);
                }

                var sortList = sortColumn == 0 ? productList.OrderByDescending(t => t.DisplayOrder).ToList() : productList;
                var proList = sortList.Select(MapperFromProduct).ToList();
                //分页对象
                PageModel pageModel = new PageModel(pageSize, page, totalCount);

                //获取日期对应价格
                if (!string.IsNullOrEmpty(priceTime))
                {
                    var sbId = new System.Text.StringBuilder();
                    proList.ForEach(x => sbId.AppendFormat(",{0}", x.Pid));
                    if (sbId.Length > 0)
                    {
                        sbId.Remove(0, 1);
                        var priceList = ProductPriceManager.GetDayList(sbId.ToString(), priceTime);
                        foreach (var item in priceList)
                        {
                            foreach (var pro in proList)
                            {
                                if (pro.Pid == item.Pid)
                                {
                                    pro.ShopPrice = item.Price;
                                    break;
                                }
                            }
                        }
                    }
                }

                //视图对象
                StoreSearchModel model = new StoreSearchModel()
                {
                    Word = word,
                    SortColumn = sortColumn,
                    SortDirection = sortDirection,
                    PageModel = pageModel,
                    ProductList = proList
                };
                return model;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }

        /// <summary>
        /// 店铺 商品搜索
        /// </summary>
        /// <returns></returns>
        public StoreSearchModel Search(int storeId, int cateId, int page, string word = "", int pageSize = 20, int priceStart = 0, int priceEnd = 0, int sortColumn = 0, int sortDirection = 0, string priceTime = "")
        {
            try
            {
                page = page < 1 ? 1 : page;

                //商品总数量
                int totalCount = 0;
                //商品列表
                List<PartProductInfo> productList = null;
                if (!string.IsNullOrEmpty(word))
                    Searches.SearchStoreProducts(pageSize, page, word, storeId, cateId, priceStart, priceEnd, sortColumn, sortDirection, ref totalCount, ref productList, 2);
                else
                {
                    totalCount = Products.GetStoreClassProductCount(cateId, 0, 0, storeId, 2);
                    productList =
                        Products.GetStoreClassProductList(pageSize, page, cateId, storeId, priceStart, priceEnd, sortColumn, sortDirection, 2);
                }

                var sortList = sortColumn == 0 ? productList.OrderByDescending(t => t.DisplayOrder).ToList() : productList;
                var proList = sortList.Select(MapperFromProduct).ToList();
                //分页对象
                PageModel pageModel = new PageModel(pageSize, page, totalCount);

                //获取日期对应价格
                if (!string.IsNullOrEmpty(priceTime))
                {
                    var sbId = new System.Text.StringBuilder();
                    proList.ForEach(x => sbId.AppendFormat(",{0}", x.Pid));
                    if (sbId.Length > 0)
                    {
                        sbId.Remove(0, 1);
                        var priceList = ProductPriceManager.GetDayList(sbId.ToString(), priceTime);
                        foreach (var item in priceList)
                        {
                            foreach (var pro in proList)
                            {
                                if (pro.Pid == item.Pid)
                                {
                                    pro.DiscountPrice = item.Price;
                                    break;
                                }
                            }
                        }
                    }
                }

                //视图对象
                StoreSearchModel model = new StoreSearchModel()
                {
                    Word = word,
                    SortColumn = sortColumn,
                    SortDirection = sortDirection,
                    PageModel = pageModel,
                    ProductList = proList
                };
                return model;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }

        /// <summary>
        /// 商品详情
        /// </summary>
        /// <param name="pid"></param>
        /// <returns></returns>
        public ProductModel Product(int pid)
        {
            try
            {
                //判断商品是否存在
                ProductInfo productInfo = Products.GetProductById(pid);
                var List = Products.GetProductSkuItemInfoList(pid);
                var attrid = 0;
                foreach (var item in List)
                {
                    ExtProductSKUItemInfo esku = new ExtProductSKUItemInfo();
                    attrid = esku.AttrId = item.AttrId;
                }
                if (attrid > 0)
                {
                    int salecount = Products.GetProductSkuAllsalecount(productInfo.SKUGid, attrid);
                    productInfo.SaleCount = salecount;//获取sku产品总销量
                }

                if (productInfo == null)
                    throw new Exception("你访问的商品不存在");

                ////店铺信息
                //StoreInfo storeInfo = Stores.GetStoreById(productInfo.StoreId);
                //if (storeInfo.State != (int)StoreState.Open)
                //    new Exception("你访问的商品不存在");

                //商品存在时
                ProductModel model = new ProductModel();
                //商品id
                model.Pid = pid;
                //商品信息
                model.ProductInfo = productInfo;
                //商品分类
                model.CategoryInfo = Categories.GetCategoryById(productInfo.CateId);
                //商品品牌
                model.BrandInfo = Brands.GetBrandById(productInfo.BrandId);
                //商品图片列表
                model.ProductImageList = Products.GetProductImageList(pid);
                //商品SKU列表
                model.CurrProductSkuList = Products.GetProductSkuItemInfoList(pid);

                //扩展商品属性列表
                model.ExtProductAttributeList = Products.GetExtProductAttributeList(pid);
                //商品SKU列表
                model.ProductSKUList = Products.GetProductExitingSkuListBySkuGid(productInfo.SKUGid);
                //商品库存数量
                model.StockNumber = Products.GetProductStockNumberByPid(pid);

                //单品促销
                model.SinglePromotionInfo = Promotions.GetSinglePromotionByPidAndTime(pid, DateTime.Now);
                //买送促销活动列表
                model.BuySendPromotionList = Promotions.GetBuySendPromotionList(productInfo.StoreId, pid, DateTime.Now);
                //赠品促销活动
                model.GiftPromotionInfo = Promotions.GetGiftPromotionByPidAndTime(pid, DateTime.Now);
                //赠品列表
                if (model.GiftPromotionInfo != null)
                    model.ExtGiftList = Promotions.GetExtGiftList(model.GiftPromotionInfo.PmId);
                //套装商品列表
                model.SuitProductList = Promotions.GetProductAllSuitPromotion(pid, DateTime.Now);
                //满赠促销活动
                model.FullSendPromotionInfo = Promotions.GetFullSendPromotionByStoreIdAndPidAndTime(productInfo.StoreId, pid, DateTime.Now);
                //满减促销活动
                model.FullCutPromotionInfo = Promotions.GetFullCutPromotionByStoreIdAndPidAndTime(productInfo.StoreId, pid, DateTime.Now);

                //广告语
                model.Slogan = model.SinglePromotionInfo == null ? "" : model.SinglePromotionInfo.Slogan;
                //商品促销信息
                model.PromotionMsg = Promotions.GeneratePromotionMsgForWeApp(model.SinglePromotionInfo, model.BuySendPromotionList, model.FullSendPromotionInfo, model.FullCutPromotionInfo);
                //商品折扣价格
                model.DiscountPrice = Promotions.ComputeDiscountPrice(model.ProductInfo.ShopPrice, model.SinglePromotionInfo);

                //关联商品列表
                //model.RelateProductList = Products.GetRelateProductList(pid);

                ////更新浏览历史
                //if (WorkContext.Uid > 0)
                //    Asyn.UpdateBrowseHistory(WorkContext.Uid, pid);
                ////更新商品统计
                //Asyn.UpdateProductStat(pid, WorkContext.RegionId);

                return model;
            }
            catch (Exception e)
            {
                Trace.TraceError(e.Message);
                Trace.TraceError(e.Source);
                throw;
            }
        }

        /// <summary>
        /// 获取商品的SKU信息
        /// </summary>
        /// <param name="pid"></param>
        /// <returns></returns>
        public ProductSkuInfoModel GetProductSkuInfo(int pid)
        {
            try
            {
                //判断商品是否存在
                ProductInfo productInfo = Products.GetProductById(pid);
                if (productInfo == null)
                    throw new Exception("你访问的商品不存在");
                //商品存在时
                ProductSkuInfoModel model = new ProductSkuInfoModel();
                //商品id
                model.Pid = pid;
                //商品SKU列表
                model.CurrProductSkuList = Products.GetProductSkuItemInfoList(pid);
                //商品SKU列表
                model.ProductSKUList = Products.GetProductExitingSkuListBySkuGid(productInfo.SKUGid);
                return model;
            }
            catch (Exception e)
            {
                Trace.TraceError(e.Message);
                Trace.TraceError(e.Source);
                throw;
            }
        }

        /// <summary>
        /// 获取商品的基本信息
        /// </summary>
        /// <param name="pid"></param>
        /// <returns></returns>
        public PartProductInfo GetPartProductInfo(int pid)
        {
            try
            {
                return Products.GetPartProductById(pid);
            }
            catch (Exception e)
            {
                Trace.TraceError(e.Message);
                Trace.TraceError(e.Source);
                throw;
            }
        }

        /// <summary>
        /// 获取日期库存
        /// </summary>
        /// <param name="pid"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <returns></returns>
        public bool GetRecyleStock(int pid, string startTime, string endTime)
        {
            try
            {
                var bSTime = new DateTime(1900, 1, 1);
                var bETime = new DateTime(1900, 1, 1);
                if (!string.IsNullOrEmpty(startTime) && !string.IsNullOrEmpty(endTime))
                {
                    DateTime.TryParse(startTime, out bSTime);
                    DateTime.TryParse(endTime, out bETime);
                }
                else
                {
                    throw new Exception("请选择预定时间");
                }
                var days = (bETime.Date - bSTime.Date).Days;
                if (days <= 0)
                    throw new Exception("请检查预定时间");
                //商品库存
                var stock = Products.GetProductStockByPid(pid);
                for (int i = 0; i < days; i++)
                {
                    var date = bSTime.AddDays(i);
                    var history = ProductBookStockManager.GetBookStock(pid, date);
                    if (stock.RecycleNumber <= history)
                        return false;
                }
                return true;
            }
            catch (Exception e)
            {
                Trace.TraceError(e.Message);
                throw;
            }
        }

        /// <summary>
        /// 获取当前正在免费领取的优惠券类型
        /// </summary>
        /// <param name="storeId"></param>
        /// <returns></returns>
        public List<CouponTypeInfo> GetSendingCouponTypeList(int storeId)
        {
            try
            {
                var result = Coupons.GetSendingCouponTypeList(storeId, DateTime.Now).Where(t => t.SendMode == 0).ToList();
                return result;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }

        /// <summary>
        /// 商品评价
        /// </summary>
        /// <param name="pid"></param>
        /// <param name="reviewType"></param>
        /// <param name="page"></param>
        /// <param name="attrid"></param>
        /// <param name="skugid"></param>
        /// <returns></returns>
        public AjaxProductReviewListModel ProductReviewList(int pid, int page, int reviewType = 0)
        {
            try
            {
                if (reviewType < 0 || reviewType > 3) reviewType = 0;
                //判断商品是否存在
                ProductInfo productInfo = Products.GetProductById(pid);
                var skuList = Products.GetProductSkuItemInfoList(pid);
                var attrid = 0;
                foreach (var item in skuList)
                {
                    attrid = item.AttrId;
                }
                if (productInfo == null)
                    throw new Exception("你访问的商品不存在");
                PageModel pageModel1 = new PageModel(10, page, ProductReviews.GetProductReviewCount(attrid, productInfo.SKUGid, reviewType));//一类商品的评价数量
                PageModel pageModel = new PageModel(10, page, ProductReviews.GetProductReviewCount(pid, reviewType));//单个商品的评价数量
                if (attrid <= 0)
                {
                    AjaxProductReviewListModel model = new AjaxProductReviewListModel()
                    {
                        Pid = pid,
                        ReviewType = reviewType,
                        PageModel = pageModel,
                        ProductReviewList = ProductReviews.GetProductReviewList(pid, reviewType, pageModel.PageSize, pageModel.PageNumber)
                    };
                    return model;
                }
                else
                {
                    AjaxProductReviewListModel model = new AjaxProductReviewListModel()
                    {
                        Pid = pid,
                        ReviewType = reviewType,
                        PageModel = pageModel1,
                        ProductReviewList = ProductReviews.GetProductTypeReviewList(attrid, reviewType, productInfo.SKUGid, pageModel.PageSize, pageModel.PageNumber)//显示sku所有的商品评论
                    };
                    return model;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }

        /// <summary>
        /// 批量更新商品销量
        /// </summary>
        /// <param name="pids">产品编号,逗号分开</param>
        /// <param name="min">最小值</param>
        /// <param name="max">最大值</param>
        /// <param name="password">秘钥</param>
        /// <returns></returns>
        public bool BatchUpdateProductSale(string pids, int min, int max, string password)
        {
            if (password != "qd711688") return false;
            ProductManager.UpdateProductSaleCount(pids, min, max);
            return true;
        }

        #endregion 店铺商品

        #region 积分设置

        /// <summary>
        /// 获取店铺等级积分设置
        /// </summary>
        /// <param name="storeId"></param>
        /// <returns></returns>
        public CreditConfigInfo GetStoreCreditConfigInfo(int storeId)
        {
            try
            {
                return StoreConfigManager.GetStoreCreditConfigInfo(storeId);
            }
            catch (Exception e)
            {
                Trace.TraceError(e.Message);
                throw;
            }
        }

        #endregion 积分设置

        #region 组件

        /// <summary>
        /// 首页定制
        /// </summary>
        /// <param name="storeId">店铺ID</param>
        /// <param name="code">顶部轮播index_banner,导航按钮index_nav_icon,商品列表index_product,首页商品组件index_pic_area</param>
        /// <param name="position">所在的首页区域，主要针对图片组件；0：未定义， 1:首页搜索框下，2：首页导航按钮下，3：首页内容下，4：首页商品下</param>
        /// <returns></returns>
        public WidgetModel GetWidgetList(int storeId, string code, int position = 0)
        {
            try
            {
                var result = new WidgetModel { Widget = WidgetManager.GetWidget(storeId, code) };
                if (result.Widget == null || !result.Widget.IsActive)
                    return null;
                result.Config = WidgetManager.GetConfigShowList(result.Widget.WId, position).Select(t => new WidgetConfigOutDto()
                {
                    CId = t.CId,
                    IsShow = t.IsShow,
                    LinkType = t.LinkType,
                    LinkValue = JsonConvert.DeserializeObject<LinkValue>(t.LinkValue),
                    ShowImg = t.ShowImg,
                    ShowName = t.ShowName,
                    DisplayOrder = t.DisplayOrder,
                    WId = t.WId,
                    DisplayCount = t.DisplayCount,
                    DisplayType = t.DisplayType,
                    DisplayPosition = t.DisplayPosition,
                    CustomerFeatures = JsonConvert.DeserializeObject<IList<LinkValue>>(t.CustomerFeatures) ?? new List<LinkValue>()
                }).ToList();

                if (!code.Equals("index_product"))
                {
                    return result;
                }
                foreach (var config in result.Config)
                {
                    switch (config.LinkValue.Id)
                    {
                        case "new":
                            config.DisplayProductInfos = Products.GetStoreTraitProductList(config.DisplayCount, storeId, 0, 2).Select(MapperFromProduct).ToList();
                            break;

                        case "hot":
                            config.DisplayProductInfos = Products.GetStoreTraitProductList(config.DisplayCount, storeId, 0, 1).Select(MapperFromProduct).ToList();
                            break;

                        case "best":
                            config.DisplayProductInfos = Products.GetStoreTraitProductList(config.DisplayCount, storeId, 0, 0).Select(MapperFromProduct).ToList();
                            break;

                        default:
                            config.DisplayProductInfos = new List<ProductListOutDto>();
                            break;
                    }
                }
                return result;
            }
            catch (Exception e)
            {
                Trace.TraceError(e.Message);
                throw;
            }
        }

        /// <summary>
        /// 获取单个组件的配置信息
        /// </summary>
        /// <param name="storeId">店铺ID</param>
        /// <param name="cid">CID</param>
        /// <returns></returns>

        public WidgetConfigOutDto GetWidgetConfig(int storeId, int cid)
        {
            if (cid <= 0) throw new ArgumentOutOfRangeException(nameof(cid));
            var t = WidgetManager.GetConfig(cid);
            if (t == null) throw new Exception("未找到配置");
            try
            {
                var config = new WidgetConfigOutDto
                {
                    CId = t.CId,
                    IsShow = t.IsShow,
                    LinkType = t.LinkType,
                    LinkValue = JsonConvert.DeserializeObject<LinkValue>(t.LinkValue),
                    ShowImg = t.ShowImg,
                    ShowName = t.ShowName,
                    DisplayOrder = t.DisplayOrder,
                    WId = t.WId,
                    DisplayCount = t.DisplayCount,
                    DisplayType = t.DisplayType,
                    DisplayPosition = t.DisplayPosition,
                    CustomerFeatures = JsonConvert.DeserializeObject<IList<LinkValue>>(t.CustomerFeatures) ?? new List<LinkValue>()
                };
                if (config.LinkValue == null) return config;
                switch (config.LinkValue.Id)
                {
                    case "new":
                        config.DisplayProductInfos = Products.GetStoreTraitProductList(config.DisplayCount, storeId, 0, 2).Select(MapperFromProduct).ToList();
                        break;

                    case "hot":
                        config.DisplayProductInfos = Products.GetStoreTraitProductList(config.DisplayCount, storeId, 0, 1).Select(MapperFromProduct).ToList();
                        break;

                    case "best":
                        config.DisplayProductInfos = Products.GetStoreTraitProductList(config.DisplayCount, storeId, 0, 0).Select(MapperFromProduct).ToList();
                        break;

                    default:
                        config.DisplayProductInfos = new List<ProductListOutDto>();
                        break;
                }
                return config;
            }
            catch (Exception e)
            {
                Trace.TraceError(e.Message);
                throw;
            }
        }

        /// <summary>
        /// 获取店铺预约列表
        /// </summary>
        /// <param name="storeId">店铺ID</param>
        /// <param name="accountName">客户账号</param>
        /// <param name="productName">产品名</param>
        /// <param name="consultMessage">消息内容</param>
        /// <param name="startTime">开始时间</param>
        /// <param name="endTime">结束时间</param>
        /// <param name="pid">产品ID</param>
        /// <param name="pageNumber">当前页</param>
        /// <param name="pageSize">每页显示多少条</param>
        /// <returns></returns>
        public ProductAppointListModel GetAppointList(int storeId, string accountName = "", string productName = "", string consultMessage = "", string startTime = "", string endTime = "", int pid = -1, int pageNumber = 1, int pageSize = 15)
        {
            int uid = Users.GetUidByAccountName(accountName);

            var page = ProductAppointManager.List(uid, pid, startTime, endTime, pageNumber, pageSize, storeId);
            PageModel pageModel = new PageModel(pageSize, pageNumber, Convert.ToInt32(page.TotalItems));
            ProductAppointListModel model = new ProductAppointListModel()
            {
                Result = page.Items,
                PageModel = pageModel,
                AccountName = accountName,
                Pid = pid,
                ProductName = string.IsNullOrWhiteSpace(productName) ? "选择商品" : productName,

                AppointStartTime = startTime,
                AppointEndTime = endTime
            };
            return model;
        }

        /// <summary>
        /// 更新商品预约状态
        /// </summary>
        /// <param name="aid">商品咨询id</param>
        /// <param name="state">状态0:待确认，1：已取消，2：已确认，3：已拒绝</param>
        /// <returns></returns>
        public bool UpdateAppointState(int aid = -1, int state = -1)
        {
            var appoint = ProductAppointManager.Get(aid);
            if (appoint == null)
                return false;

            return ProductAppointManager.UpdateAppointStatus(aid, state);
        }

        /// <summary>
        /// 获取预约
        /// </summary>
        /// <param name="aid">预约记录ID</param>
        /// <returns></returns>
        public ProductAppoint GetAppoint(int aid)
        {
            return ProductAppointManager.Get(aid);
        }

        /// <summary>
        /// 删除商品预约
        /// </summary>
        /// <param name="aid">商品咨询id</param>
        /// <returns></returns>
        public bool DelAppoint(int aid)
        {
            ProductAppointManager.DeleteAppoint(aid);
            return true;
        }

        /// <summary>
        /// 获取定时商品列表
        /// </summary>
        /// <param name="storeId">店铺ID</param>
        /// <param name="productName">搜索名称</param>
        /// <param name="pageSize">每页多少条</param>
        /// <param name="pageNumber">页码</param>
        /// <returns></returns>
        public TimeProductListModel TimeProductList(int storeId, string productName = "", int pageSize = 15, int pageNumber = 1)
        {
            var setting = TimeProductManager.GetTimeProductSettingByStoreId(storeId);
            if (setting == null)
            {
                setting = new TimeProductSetting
                {
                    Name = "限时商品",
                    ShowImg = "",
                    ShowIndex = true,
                    StoreId = storeId,
                    ShowIndexMax = 4
                };
                TimeProductManager.AddTimeProductSetting(setting);
            }
            PageModel pageModel = new PageModel(pageSize, pageNumber, AdminProducts.GetTimeProductCount(storeId, productName));
            TimeProductListModel model = new TimeProductListModel()
            {
                PageModel = pageModel,
                TimeProductList = AdminProducts.GetTimeProductList(pageSize, pageNumber, storeId, productName, $" AND [onsalestate]=2 AND [outsalestate]=1 "),
                ProductName = productName,
                Setting = setting
            };

            return model;
        }

        /// <summary>
        /// 获取定时商品首页列表
        /// </summary>
        /// <param name="storeId">店铺ID</param>
        /// <returns></returns>
        public TimeProductListModel TimeProductIndexList(int storeId)
        {
            var setting = TimeProductManager.GetTimeProductSettingByStoreId(storeId);
            if (setting == null)
            {
                setting = new TimeProductSetting
                {
                    Name = "限时商品",
                    ShowImg = "",
                    ShowIndex = true,
                    StoreId = storeId,
                    ShowIndexMax = 4,
                    DisplayPosition = 1
                };
                TimeProductManager.AddTimeProductSetting(setting);
            }
            PageModel pageModel = new PageModel(setting.ShowIndexMax, 1, AdminProducts.GetTimeProductCount(storeId, ""));
            TimeProductListModel model = new TimeProductListModel()
            {
                PageModel = pageModel,
                TimeProductList = AdminProducts.GetTimeProductList(setting.ShowIndexMax, 1, storeId, "", $" AND [onsalestate]=2 AND [outsalestate]=1 "),
                ProductName = "",
                Setting = setting
            };

            return model;
        }

        /// <summary>
        /// 获取拼团商品列表
        /// </summary>
        /// <param name="storeId">店铺ID</param>
        /// <param name="pageSize">每页显示多少条</param>
        /// <param name="pageNumber">当前页</param>
        /// <returns></returns>
        public GroupBuyProductListModel GetGroupBuyProduct(int storeId, int pageSize = 15, int pageNumber = 1)
        {
            var setting = GroupBuyManager.GetGroupBuySettingByStoreId(storeId);
            if (setting == null)
            {
                setting = new GroupBuySetting
                {
                    Name = "商品团购",
                    ShowImg = "",
                    ShowIndex = true,
                    StoreId = storeId
                };
                GroupBuyManager.AddGroupBuySetting(setting);
            }
            var ps = GroupBuyManager.GetStoreGroupBuyProducts(storeId, pageNumber, pageSize);
            var pageModel = new PageModel(pageSize, pageNumber, Convert.ToInt32(ps.TotalItems));
            var items = ps.Items.Select(CastGroupBuyProductModel).ToList();
            var result = new GroupBuyProductListModel
            {
                Page = pageModel,
                Items = items,
                Setting = setting
            };
            return result;
        }

        /// <summary>
        /// 获取拼团商品首页列表
        /// </summary>
        /// <param name="storeId">店铺ID</param>
        /// <returns></returns>
        public GroupBuyProductListModel GetGroupBuyIndexProduct(int storeId)
        {
            var setting = GroupBuyManager.GetGroupBuySettingByStoreId(storeId);
            if (setting == null)
            {
                setting = new GroupBuySetting
                {
                    Name = "商品团购",
                    ShowImg = "",
                    ShowIndex = true,
                    StoreId = storeId,
                    ShowIndexMax = 4,
                    DisplayPosition = 1
                };
                GroupBuyManager.AddGroupBuySetting(setting);
            }
            var ps = GroupBuyManager.GetStoreGroupBuyProducts(storeId, 1, setting.ShowIndexMax);
            var pageModel = new PageModel(setting.ShowIndexMax, 1, Convert.ToInt32(ps.TotalItems));
            var items = ps.Items.Select(CastGroupBuyProductModel).ToList();
            var result = new GroupBuyProductListModel
            {
                Page = pageModel,
                Items = items,
                Setting = setting
            };
            return result;
        }

        /// <summary>
        /// 获取单个商品的拼团信息
        /// </summary>
        /// <param name="storeId">店铺ID</param>
        /// <param name="pid">产品ID</param>
        /// <returns></returns>
        public GroupBuyProductModel GetGroupBuyProductInfo(int storeId, int pid)
        {
            var info = GroupBuyManager.GetGroupBuyProductInfo(storeId, pid);
            return CastGroupBuyProductModel(info);
        }

        private GroupBuyProductModel CastGroupBuyProductModel(GroupBuyProduct p)
        {
            if (p == null) throw new ApiException(ExceptionCode.DataNotFound, "拼团信息");
            var gb = GroupBuyManager.GetGroupBuy(p.GroupId);
            if (gb == null) throw new ApiException(ExceptionCode.DataNotFound, "拼团信息");
            var pInfo = Products.GetPartProductById(p.Pid);
            var gbModel = new GroupBuyModel
            {
                EndTime = gb.EndTime,
                Id = gb.Id,
                LimitBuyCount = gb.LimitBuyCount,
                LimitBuyerCount = gb.LimitBuyerCount,
                LimitHour = gb.LimitHour,
                LimitJoinCount = gb.LimitJoinCount,
                Name = gb.Name,
                StartTime = gb.StartTime,
                Status = gb.Status,
                StoreId = gb.StoreId
            };

            //计算剩余拼团(假拼团，只改变显示数量)
            var count = gbModel.LimitBuyerCount - (pInfo.SaleCount % gbModel.LimitBuyerCount);
            //防止出现0
            count = count < 1 ? gbModel.LimitBuyerCount : count;

            return new GroupBuyProductModel
            {
                Id = p.Id,
                GroupBuyPrice = p.GroupBuyPrice,
                Product = pInfo,
                GroupBuy = gbModel,
                BuyStatus = $"还差{count}人"
            };
        }

        #endregion 组件

        #region 生成二维码

        /// <summary>
        /// 获取小程序二维码
        /// </summary>
        /// <param name="storeId">店铺ID</param>
        /// <param name="path">包含的路径</param>
        /// <param name="weAppId">小程序配置ID</param>
        /// <param name="storeAppId">自动打包的小程序ID</param>
        /// <returns></returns>
        public string GetWxaCodeFile(int storeId, string path, int weAppId = 0, int storeAppId = 0)
        {
            if (storeId < 0) throw new ArgumentOutOfRangeException(nameof(storeId));
            try
            {
                if (storeAppId == 0 && weAppId == 0)
                {
                    //采用自动打包的默认第一个
                    storeAppId = StoreApplicationManager.GetStoreApplications(storeId).First()?.StoreAppId ?? 0;
                }
                if (storeAppId == 0)
                {
                    var acode = WxQRCode.GetWxaCode(storeId, path, weAppId);
                    return acode;
                }
                return WxQRCode.GetWxaCodeByStoreAppId(storeId, path, storeAppId);
            }
            catch (Exception e)
            {
                Trace.TraceError(e.Message);
                throw;
            }
        }

        #endregion 生成二维码

        #region 门店

        /// <summary>
        /// 门店列表
        /// </summary>
        /// <param name="storeId">店铺ID</param>
        /// <param name="latitude">当前位置的纬度</param>
        /// <param name="longitude">当前位置的经度</param>
        /// <param name="pageNumber">第几页</param>
        /// <param name="pageSize">一页多少条</param>
        /// <returns></returns>
        public BranchListModel GetBranchList(int storeId, double latitude = 0, double longitude = 0, int pageNumber = 1, int pageSize = 15)
        {
            var dbList = BranchManager.GetListPage(storeId, pageNumber, pageSize);
            //坐标不存在时，用店铺坐标
            if (latitude == 0 || longitude == 0)
            {
                var storeModel = Stores.GetStoreById(storeId);
                if (storeModel != null && (!string.IsNullOrEmpty(storeModel.Location)))
                {
                    string[] location = storeModel.Location.Split(',');
                    if (location.Length > 1)
                    {
                        latitude = double.Parse(location[0]);
                        longitude = double.Parse(location[1]);
                    }
                }
            }

            var list = new List<BranchModel>();
            foreach (var item in dbList.Items)
            {
                var info = new BranchModel() { bid = item.Bid, name = item.Name };

                string[] location = item.Location.Split(',');   //经纬度
                if (string.IsNullOrEmpty(item.Location) || location.Length < 2)
                {
                    info.latitude = info.longitude = string.Empty;
                    info.distance = "未知"; //距离
                }
                else
                {
                    info.latitude = location[0];
                    info.longitude = location[1];
                    info.metre = LocationHelper.GetDistance(latitude, longitude, double.Parse(info.latitude), double.Parse(info.longitude));
                    if (info.metre > 1000)
                        info.distance = string.Format("{0} km", Math.Round((info.metre * 0.001), 1)); //距离, 1km范围以上
                    else
                        info.distance = string.Format("{0} m", Math.Round(info.metre, 1));            //距离, 1km范围内
                }
                list.Add(info);
            }

            list.Sort((x, y) => x.metre.CompareTo(y.metre));//升序

            var model = new BranchListModel()
            {
                List = list,
                PageModel = new PageModel(pageNumber, pageSize, (int)dbList.TotalItems)
            };
            return model;
        }

        /// <summary>
        /// 门店详情
        /// </summary>
        /// <param name="bid">门店ID</param>
        /// <returns></returns>
        public BranchInfo GetBranch(int bid)
        {
            return BranchManager.Get(bid);
        }

        #endregion 门店

        #region 产品的日期价

        /// <summary>
        /// 产品的日期价格列表
        /// </summary>
        /// <param name="pid"></param>
        /// <returns></returns>
        public IList<ProductPrice> ProductPriceList(int pid)
        {
            var productList = ProductPriceManager.GetList(pid);
            return productList;
        }

        #endregion 产品的日期价

        /// <summary>
        /// 判断是否开通分销功能
        /// </summary>
        /// <param name="storeId">店铺ID</param>
        /// <returns></returns>
        public bool CheckDistributor(int storeId)
        {
            return StoreInfoManager.CheckDistributor(storeId);
        }

        private ProductListOutDto MapperFromProduct(PartProductInfo item)
        {
            var p = new ProductListOutDto
            {
                AddTime = item.AddTime,
                BrandId = item.BrandId,
                CateId = item.CateId,
                CostPrice = item.CostPrice,
                DisplayOrder = item.DisplayOrder,
                IsBest = item.IsBest,
                IsHot = item.IsHot,
                IsNew = item.IsNew,
                MarketPrice = item.MarketPrice,
                Name = item.Name,
                Pid = item.Pid,
                PSN = item.PSN,
                ReviewCount = item.ReviewCount,
                StoreId = item.StoreId,
                SKUGid = item.SKUGid,
                SaleCount = item.SaleCount,
                ShopPrice = item.ShopPrice,
                ShowImg = item.ShowImg,
                Star1 = item.Star1,
                Star2 = item.Star2,
                Star3 = item.Star3,
                Star4 = item.Star4,
                Star5 = item.Star5,
                State = item.State,
                StoreCid = item.StoreCid,
                StoreSTid = item.StoreSTid,
                VisitCount = item.VisitCount,
                Weight = item.Weight,
                BannerImg = item.BannerImg,
                StockNumber = Products.GetProductStockNumberByPid(item.Pid),
                DiscountPrice = item.ShopPrice
            };
            return p;
        }
    }
}